package org.Yiran.timetale_re.util;

import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.RegistryObject;
import org.Yiran.timetale_re.item.tool.screwdriver.modules.IModule;

import java.lang.reflect.Field;

/**
 * 起子模块工具类
 * <p>
 * 提供处理起子模块相关的通用工具方法
 * </p>
 */
public class ScrewdriverModuleUtils {

    /**
     * 根据模块ID获取对应的物品栈
     * <p>
     * 根据模块ID获取对应的模块物品栈
     * </p>
     *
     * @param moduleId 模块ID
     * @return 模块物品栈
     */
    public static ItemStack getModuleItemStack(String moduleId) {
        // 通过反射和注册系统自动查找对应的物品
        try {
            // 获取ItemsRegister类
            Class<?> itemsRegisterClass = getItemsRegisterClass();

            // 获取所有公共静态字段
            Field[] fields = getItemsRegisterFields(itemsRegisterClass);

            // 遍历字段查找匹配的RegistryObject
            return findMatchingModuleItem(fields, moduleId);
        } catch (Exception ignored) {
        }

        // 如果找不到匹配项，返回空物品栈
        return ItemStack.EMPTY;
    }
    
    /**
     * 获取ItemsRegister类
     * <p>
     * 通过类名获取ItemsRegister类的Class对象
     * </p>
     *
     * @return ItemsRegister类的Class对象
     * @throws ClassNotFoundException 如果找不到指定的类
     */
    private static Class<?> getItemsRegisterClass() throws ClassNotFoundException {
        return Class.forName("org.Yiran.timetale_re.item.ItemsRegister");
    }
    
    /**
     * 获取ItemsRegister类的所有公共静态字段
     * <p>
     * 获取ItemsRegister类中定义的所有公共字段
     * </p>
     *
     * @param itemsRegisterClass ItemsRegister类的Class对象
     * @return 公共字段数组
     */
    private static Field[] getItemsRegisterFields(Class<?> itemsRegisterClass) {
        return itemsRegisterClass.getFields();
    }
    
    /**
     * 查找匹配的模块物品
     * <p>
     * 遍历字段数组，查找与模块ID匹配的RegistryObject并返回对应的物品栈
     * </p>
     *
     * @param fields   字段数组
     * @param moduleId 模块ID
     * @return 匹配的物品栈，如果找不到则返回空物品栈
     */
    private static ItemStack findMatchingModuleItem(Field[] fields, String moduleId) {
        for (Field field : fields) {
            if (isMatchingField(field, moduleId)) {
                return createItemStackFromField(field);
            }
        }
        return ItemStack.EMPTY;
    }
    
    /**
     * 检查字段是否与模块ID匹配
     * <p>
     * 检查字段名称是否与模块ID忽略大小写匹配
     * </p>
     *
     * @param field    字段
     * @param moduleId 模块ID
     * @return 如果字段名称与模块ID匹配返回true，否则返回false
     */
    private static boolean isMatchingField(Field field, String moduleId) {
        return field.getName().equalsIgnoreCase(moduleId);
    }
    
    /**
     * 从字段创建物品栈
     * <p>
     * 从字段中获取RegistryObject并创建对应的物品栈
     * </p>
     *
     * @param field 字段
     * @return 物品栈，如果无法创建则返回空物品栈
     */
    private static ItemStack createItemStackFromField(Field field) {
        try {
            Object obj = field.get(null);
            if (obj instanceof RegistryObject<?> registryObject) {
                if (registryObject.isPresent()) {
                    return new ItemStack((net.minecraft.world.level.ItemLike) registryObject.get());
                }
            }
        } catch (IllegalAccessException ignored) {
        }
        return ItemStack.EMPTY;
    }

    /**
     * 处理移除模块后的物品分配
     * <p>
     * 将模块物品添加到玩家物品栏或掉落在地上
     * </p>
     *
     * @param player 玩家
     * @param module 被移除的模块
     */
    public static void handleModuleRemoval(Player player, IModule module) {
        String moduleId = module.getModuleId();
        ItemStack moduleStack = getModuleItemStack(moduleId);
        if (!moduleStack.isEmpty()) {
            processModuleItemAddition(player, moduleStack);
        }
    }
    
    /**
     * 处理模块物品添加
     * <p>
     * 尝试将模块物品添加到玩家物品栏，如果失败则掉落在地上
     * </p>
     *
     * @param player      玩家
     * @param moduleStack 模块物品栈
     */
    private static void processModuleItemAddition(Player player, ItemStack moduleStack) {
        // 尝试将模块添加到玩家物品栏
        boolean added = player.getInventory().add(moduleStack);

        // 无论是否添加成功，都要确保在创造模式下也掉落物品
        // 这样可以避免在物品栏满时模块消失的问题
        if (shouldDropModuleItem(player, added)) {
            // 如果物品栏已满，或玩家在创造模式下，则将模块掉落在玩家脚下
            player.drop(moduleStack, false);
        }
    }
    
    /**
     * 检查是否应该掉落模块物品
     * <p>
     * 检查物品是否应该掉落在玩家脚下，当物品栏已满或玩家在创造模式时
     * </p>
     *
     * @param player 玩家
     * @param added  物品是否成功添加到物品栏
     * @return 如果应该掉落物品返回true，否则返回false
     */
    private static boolean shouldDropModuleItem(Player player, boolean added) {
        return !added || player.getAbilities().instabuild;
    }
}